<template></template>

<script setup>
import { onMounted, onUnmounted } from "vue";

// 可用的表情符号列表
const emojis = ["😊", "😎", "😍", "🤩", "🥳", "😂", "🤣", "😃", "😄", "😁"];
// 重力加速度模拟
const gravity = 0.5;
// 弹跳系数 (负值使表情符号反弹)
const bounceFactor = -0.7;
// 节流间隔时间 (毫秒)
const throttleDelay = 200;

// 存储所有动画ID，用于在组件卸载时清理
const animationIds = new Set();
// 记录上次执行时间
let lastExecuted = 0;

/**
 * 节流函数
 * @param {Function} func - 要执行的函数
 * @param {number} delay - 延迟时间(毫秒)
 * @return {Function} - 节流处理后的函数
 */
function throttle(func, delay) {
  return function (...args) {
    const now = Date.now();
    if (now - lastExecuted >= delay) {
      lastExecuted = now;
      return func.apply(this, args);
    }
  };
}

/**
 * 点击事件处理函数
 * 在点击位置创建随机数量的表情符号
 */
function handleClick(event) {
  // 生成5到14个随机表情符号
  const count = Math.floor(Math.random() * 10) + 5;
  for (let i = 0; i < count; i++) {
    createEmoji(event.pageX, event.pageY);
  }
}

// 对点击处理函数应用节流
const throttledHandleClick = throttle(handleClick, throttleDelay);

/**
 * 创建并动画化单个表情符号
 * @param {number} x - 初始X坐标
 * @param {number} y - 初始Y坐标
 */
function createEmoji(x, y) {
  // 创建表情符号DOM元素
  const emojiElement = document.createElement("div");
  emojiElement.classList.add("emoji");
  // 从列表中随机选择一个表情符号
  emojiElement.textContent = emojis[Math.floor(Math.random() * emojis.length)];

  // 初始位置和速度
  let posX = x;
  let posY = y;
  // 水平速度为随机值（向左或向右）
  let velX = (Math.random() - 0.5) * 10;
  // 垂直速度为随机负值（向上运动）
  let velY = -Math.random() * 10;

  // 添加到页面
  document.body.appendChild(emojiElement);

  /**
   * 动画循环函数
   * 处理物理效果和元素位置更新
   */
  function animate() {
    // 处理垂直边界碰撞
    if (posY >= window.scrollY + window.innerHeight || posY <= 0) {
      velY *= bounceFactor;

      // 新增：当速度过小时直接移除元素
      if (Math.abs(velY) < 0.1) {
        emojiElement.style.opacity = 0;
        setTimeout(() => {
          if (document.body.contains(emojiElement)) {
            document.body.removeChild(emojiElement);
          }
        }, 100);
        return; // 停止动画循环
      }
    } else {
      // 应用重力
      velY += gravity;
    }

    // 处理水平边界碰撞
    if (posX >= window.scrollX + window.innerWidth || posX <= 0) {
      velX *= bounceFactor;
    }

    // 更新位置
    posX += velX;
    posY += velY;

    // 更新DOM元素位置
    emojiElement.style.left = `${posX}px`;
    emojiElement.style.top = `${posY}px`;

    // 当表情符号下落250px后开始淡出
    if (posY > y + 250) {
      emojiElement.style.opacity = 0;

      // 设置计时器移除元素并清理
      const animationId = setTimeout(() => {
        if (document.body.contains(emojiElement)) {
          document.body.removeChild(emojiElement);
        }
        // 从跟踪集合中移除
        animationIds.delete(animationId);
      }, 500); // 匹配CSS过渡时间
    }

    // 继续动画循环并跟踪ID
    const animationId = requestAnimationFrame(animate);
    animationIds.add(animationId);
  }

  // 启动动画
  const animationId = requestAnimationFrame(animate);
  animationIds.add(animationId);
}

// 组件挂载时添加点击事件监听器
onMounted(() => {
  document.addEventListener("click", throttledHandleClick);
});

// 组件卸载时进行清理
onUnmounted(() => {
  // 移除事件监听器
  document.removeEventListener("click", throttledHandleClick);

  // 取消所有动画帧和计时器
  animationIds.forEach((id) => {
    cancelAnimationFrame(id);
    clearTimeout(id);
  });

  // 从DOM中移除所有表情符号元素
  document.querySelectorAll(".emoji").forEach((element) => {
    if (document.body.contains(element)) {
      document.body.removeChild(element);
    }
  });
});
</script>
<style>
.emoji {
  position: absolute;
  width: 50px;
  height: 50px;
  text-align: center;
  line-height: 50px;
  font-size: 2em;
  pointer-events: none; /* 防止元素接收点击事件 */
  transition: opacity 0.5s ease-out; /* 淡出动画 */
}
</style>
